package org.zh.util;

import java.util.*;

/**
 * K1  K2 必须同时是全部key值的唯一存在
 *
 * @param <K1>
 * @param <K2>
 * @param <V>
 */
public class HashMap_<K1, K2, V> implements Map_<K1, K2, V> {

    private final Map<Object[], V> map = new HashMap<>();
    private final Map<Object, Object[]> keyMap = new HashMap<>();

    public int size() {
        return map.size();
    }

    public boolean isEmpty() {
        return size() == 0;
    }

    public boolean containsKey(Object key) {
        return keyMap.containsKey(key);
    }

    public boolean containsValue(V value) {
        return map.containsValue(value);
    }

    public V get(Object key) {
        Object[] keys = keyMap.get(key);
        return map.get(keys);
    }

    public V put(K1 key1, K2 key2, V value) {
        if (containsKey(key1)) {
            throw new RuntimeException("key1 已经存在->" + key1);
        }
        if (containsKey(key2)) {
            throw new RuntimeException("key2 已经存在->" + key2);
        }
        Object[] keys = {key1, key2};
        keyMap.put(key1, keys);
        keyMap.put(key2, keys);
        return map.put(keys, value);
    }


    private void put1(Object[] keys, V value) {
        keyMap.put(keys[0], keys);
        keyMap.put(keys[1], keys);
        map.put(keys, value);
    }

    public V remove(Object key) {
        Object[] keys = keyMap.remove(key);
        if (!keys[0].equals(key)) {
            keyMap.remove(keys[0]);
        } else {
            keyMap.remove(keys[1]);
        }
        return map.remove(keys);
    }

    public void putAll(Map_<? extends K1, ? extends K2, ? extends V> m) {
        m.unityKeySet().forEach(key -> {
            if (containsKey(key)) throw new RuntimeException("key 存在冲突  无法合并");
        });
        m.allyKeySet().forEach(key -> put1(key, m.get(key[0])));
    }

    public void clear() {
        keyMap.clear();
        map.clear();
    }

    public Set<Object> unityKeySet() {
        return keyMap.keySet();
    }

    public Set<Object[]> allyKeySet() {
        return map.keySet();
    }

    public Collection<V> values() {
        return map.values();
    }

    public Object getKey(Object key) {
        Object[] objects = keyMap.get(key);
        return objects[0] == key ? objects[1] : objects[0];
    }

    public V replace(Object key, V value) {
        if (!containsKey(key)) {
            throw new RuntimeException("key 不存在->" + key);
        }
        Object[] objects = keyMap.get(key);
        return map.replace(objects, value);
    }


    public void forEach(TrConsumer<? super K1, ? super K2, ? super V> action) {
        Objects.requireNonNull(action);
        for (Map.Entry<Object[], V> entry : map.entrySet()) {
            K1 k1;
            K2 k2;
            V v;
            try {
                k1 = (K1) entry.getKey()[0];
                k2 = (K2) entry.getKey()[1];
                v = entry.getValue();
            } catch (IllegalStateException ise) {
                throw new ConcurrentModificationException(ise);
            }
            action.accept(k1, k2, v);
        }
    }

}
